package java_thinking.unit_21._21_6;

import java.util.concurrent.*;

import static java.util.concurrent.TimeUnit.NANOSECONDS;

/**
 * @Desc:   6-16 在指定时间内获取广告信息
 *          1.Future.get() 典型应用，超时取消线程
 * @author: cww
 * @DateTime: 2019/6/12 19:10
 */

public class RenderWithTimeBudget {
    private static final Ad DEFAULT_AD = new Ad();
    private static final long TIME_BUDGET = 1000;
    private static final ExecutorService exec = Executors.newCachedThreadPool();
    Page renderPage() {
        long endNanos = System.nanoTime() + TIME_BUDGET;
        Future<Ad> adFuture = exec.submit(new FetchAdTask());
        Page page = renderPageBody();
        Ad ad = null;
        try {
            long timeLeft = endNanos - System.nanoTime();
            //有时间限制的 Future.get
            //所有get 的 timeout 参数的计算方法是将指定实现减去当前时间，可能会得到负数，当
            //java.util.concurrent 中所有与时限相关的方法都将负数视为零，因此不需要额外的处理
            ad = adFuture.get(timeLeft,NANOSECONDS);
        } catch (InterruptedException e) {
            ad = DEFAULT_AD;
        } catch (ExecutionException e) {
            ad = DEFAULT_AD;
        } catch (TimeoutException e) {
            //超时后返回默认，并且取消线程
            ad = DEFAULT_AD;
            //这里 true 表示任务线程可以在运行过程中中断
            adFuture.cancel(true);
        }
        page.setAd(ad);
        return page;

    }

    static class Ad {
    }
    Page renderPageBody() { return new Page(); }

    static class Page {
        public void setAd(Ad ad) { }
    }

    static class FetchAdTask implements Callable<Ad> {
        @Override
        public Ad call() {
            return new Ad();
        }
    }
}
